package com.woniuxy.gateway.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.gateway.common.JWTHelper;
import com.woniuxy.gateway.filter.JwtTokenAuthenticationFilter;
import com.woniuxy.gateway.handlder.AuthenticationFailHandler;
import com.woniuxy.gateway.handlder.AuthenticationSuccessHandler;
import com.woniuxy.gateway.handlder.CustomHttpBasicServerAuthenticationEntryPoint;
import com.woniuxy.gateway.handlder.SharedBatteryLogoutSuccessHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;

import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;


import javax.annotation.Resource;


@EnableWebFluxSecurity
public class SecurityConfig {
    //白名单
    @Value("${auth.url.white}")
    private String[] excludeAuthPages;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Resource
    private StringRedisTemplate srt;

    @Resource
    private JWTHelper jwtHelper;

    @Resource
    private ObjectMapper objectMapper;


    @Bean
    public SecurityWebFilterChain securityWebFilterChain(
            ServerHttpSecurity http,
            CustomHttpBasicServerAuthenticationEntryPoint customHttpBasicServerAuthenticationEntryPoint,
            AuthenticationSuccessHandler authenticationSuccessHandler,
            AuthenticationFailHandler authenticationFailHandler,
            SharedBatteryLogoutSuccessHandler sharedBatteryLogoutSuccessHandler
    ) {
        //http相关的配置，包括登入登出、异常处理、会话管理等
        //关闭基础的认证功能
        http.csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .authorizeExchange()
                .pathMatchers(excludeAuthPages).permitAll()//无需进行权限过滤的请求路径
                .pathMatchers(HttpMethod.OPTIONS).permitAll()//无需进行权限过滤的请求路径
                .anyExchange().authenticated()//无需进行权限过滤的请求路径
                .and()
                .formLogin()
                .loginPage("/login")
                .authenticationEntryPoint(customHttpBasicServerAuthenticationEntryPoint)
                //成功和失败返回
                .authenticationSuccessHandler(authenticationSuccessHandler)// 自定义authenticationSuccessHandler
                .authenticationFailureHandler(authenticationFailHandler)// 自定义authenticationFailureHandler
                .and().logout().logoutUrl("/logout")
                //超时
                .logoutSuccessHandler(sharedBatteryLogoutSuccessHandler)// 自定义logoutSuccessHandler
                .and()
                //自定义过滤器
                .addFilterAfter(new JwtTokenAuthenticationFilter(jwtHelper, objectMapper, srt, excludeAuthPages), SecurityWebFiltersOrder.HTTP_BASIC);

        return http.build();
    }
}
